﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StyleMVVM.Data;
using StyleMVVM.DependencyInjection;
using StyleMVVM.UnitTests.TestClasses.ValidationObjects.Automobile;
using StyleMVVM.Validation;
using StyleMVVM.Validation.Impl;
using StyleMVVM.Validation.Impl.Fluent;
#if NETFX_CORE
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
using Windows.ApplicationModel.Resources;

#else
using Microsoft.VisualStudio.TestTools.UnitTesting;

#endif

namespace StyleMVVM.UnitTests.Validation.Fluent
{
	[TestClass]
	public class OperatorTests : BaseTestClass
	{
		[TestMethod]
		public void IsRequired()
		{
			ResourceLoader fluentResources = new ResourceLoader("StyleMVVM.CSharp/FluentResources");
			FluentRule<Truck> wheelsRule = new FluentRule<Truck>(Container.Locate<IReflectionService>(), "WheelRule");

			wheelsRule.Property(x => x.LicensePlate).IsNotNull();

			wheelsRule.Compile(fluentResources);

			Truck newTruck = new Truck();

			RuleExecutionContext context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newTruck.LicensePlate = "Blah";

			context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);
		}

		[TestMethod]
		public void IsNullRule()
		{
			ResourceLoader fluentResources = new ResourceLoader("StyleMVVM.CSharp/FluentResources");
			FluentRule<Truck> wheelsRule = new FluentRule<Truck>(Container.Locate<IReflectionService>(), "WheelRule");

			wheelsRule.Property(x => x.LicensePlate).IsNull();

			wheelsRule.Compile(fluentResources);

			Truck newTruck = new Truck { LicensePlate = "Blah" };

			RuleExecutionContext context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newTruck.LicensePlate = null;

			context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);
		}

		[TestMethod]
		public void IsNotNullRule()
		{
			ResourceLoader fluentResources = new ResourceLoader("StyleMVVM.CSharp/FluentResources");
			FluentRule<Truck> wheelsRule = new FluentRule<Truck>(Container.Locate<IReflectionService>(), "WheelRule");

			wheelsRule.Property(x => x.LicensePlate).IsNotNull();

			wheelsRule.Compile(fluentResources);

			Truck newTruck = new Truck();

			RuleExecutionContext context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newTruck.LicensePlate = "Blah";

			context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);
		}

		[TestMethod]
		public void IsEmpty()
		{
			ResourceLoader fluentResources = new ResourceLoader("StyleMVVM.CSharp/FluentResources");
			FluentRule<Truck> wheelsRule = new FluentRule<Truck>(Container.Locate<IReflectionService>(), "WheelRule");

			wheelsRule.Property(x => x.LicensePlate).IsEmpty();

			wheelsRule.Compile(fluentResources);

			Truck newTruck = new Truck { LicensePlate = "Blah" };

			RuleExecutionContext context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newTruck.LicensePlate = string.Empty;

			context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);
		}

		[TestMethod]
		public void IsNotEmpty()
		{
			ResourceLoader fluentResources = new ResourceLoader("StyleMVVM.CSharp/FluentResources");
			FluentRule<Truck> wheelsRule = new FluentRule<Truck>(Container.Locate<IReflectionService>(), "WheelRule");

			wheelsRule.Property(x => x.LicensePlate).IsNotEmpty();

			wheelsRule.Compile(fluentResources);

			Truck newTruck = new Truck { LicensePlate = string.Empty };

			RuleExecutionContext context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newTruck.LicensePlate = "Blah";

			context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);
		}

		[TestMethod]
		public void GreaterThanOrEqualRule()
		{
			ResourceLoader fluentResources = new ResourceLoader("StyleMVVM.CSharp/FluentResources");
			FluentRule<Truck> wheelsRule = new FluentRule<Truck>(Container.Locate<IReflectionService>(), "WheelRule");

			wheelsRule.Property(x => x.Wheels).GreaterThanOrEqualTo.Value(4);

			wheelsRule.Compile(fluentResources);

			Truck newTruck = new Truck { Wheels = 3 };

			RuleExecutionContext context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newTruck.Wheels = 4;

			context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);
		}

		[TestMethod]
		public void GreaterThanRule()
		{
			ResourceLoader fluentResources = new ResourceLoader("StyleMVVM.CSharp/FluentResources");
			FluentRule<Truck> wheelsRule = new FluentRule<Truck>(Container.Locate<IReflectionService>(), "WheelRule");

			wheelsRule.Property(x => x.Wheels).GreaterThan.Value(4);

			wheelsRule.Compile(fluentResources);

			Truck newTruck = new Truck { Wheels = 4 };

			RuleExecutionContext context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newTruck.Wheels = 5;

			context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);
		}

		[TestMethod]
		public void LessThanOrEqualRule()
		{
			ResourceLoader fluentResources = new ResourceLoader("StyleMVVM.CSharp/FluentResources");
			FluentRule<Truck> wheelsRule = new FluentRule<Truck>(Container.Locate<IReflectionService>(), "WheelRule");

			wheelsRule.Property(x => x.Wheels).LessThanOrEqualTo.Value(4);

			wheelsRule.Compile(fluentResources);

			Truck newTruck = new Truck { Wheels = 5 };

			RuleExecutionContext context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newTruck.Wheels = 4;

			context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);
		}

		[TestMethod]
		public void LessThanRule()
		{
			ResourceLoader fluentResources = new ResourceLoader("StyleMVVM.CSharp/FluentResources");
			FluentRule<Truck> wheelsRule = new FluentRule<Truck>(Container.Locate<IReflectionService>(), "WheelRule");

			wheelsRule.Property(x => x.Wheels).LessThan.Value(4);

			wheelsRule.Compile(fluentResources);

			Truck newTruck = new Truck { Wheels = 4 };

			RuleExecutionContext context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newTruck.Wheels = 3;

			context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);
		}

		[TestMethod]
		public void EqualToRule()
		{
			ResourceLoader fluentResources = new ResourceLoader("StyleMVVM.CSharp/FluentResources");
			FluentRule<Car> wheelsRule = new FluentRule<Car>(Container.Locate<IReflectionService>(), "WheelRule");

			wheelsRule.Property(x => x.Wheels).EqualTo.Value(4);

			wheelsRule.Compile(fluentResources);

			Car newCar = new Car();

			RuleExecutionContext context = new RuleExecutionContext(newCar);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newCar.Wheels = 4;

			context = new RuleExecutionContext(newCar);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);
		}

		[TestMethod]
		public void NotEqualToRule()
		{
			ResourceLoader fluentResources = new ResourceLoader("StyleMVVM.CSharp/FluentResources");
			FluentRule<Car> wheelsRule = new FluentRule<Car>(Container.Locate<IReflectionService>(), "WheelRule");

			wheelsRule.Property(x => x.Wheels).NotEqualTo.Value(2);

			wheelsRule.Compile(fluentResources);

			Car newCar = new Car { Wheels = 2 };

			RuleExecutionContext context = new RuleExecutionContext(newCar);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newCar.Wheels = 4;

			context = new RuleExecutionContext(newCar);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);
		}
	}
}